<template>
  <a-spin :spinning="loading">
    <JFormContainer :disabled="disabled">
      <template #detail>
        <div class="form-content-title">表单注册信息</div>
        <a-form v-bind="formItemLayout" name="OnlinePagesForm" ref="formRef">
          <a-row>
            <a-col :span="12">
              <a-form-item label="表" v-bind="validateInfos.cgformHeadId" id="OnlinePagesForm-cgformHeadId" name="cgformHeadId">
                <api-select
                  v-model:value="formData.cgformHeadId"
                  :api="formList"
                  show-search
                  optionFilterProp="tableName"
                  resultField="records"
                  labelField="tableName"
                  valueField="id"
                  placeholder="请输入表名进行搜索"
                  allow-clear
                  :params="searchParams"
                  @change="selectForm"
                  @search="onSearch"
                />
              </a-form-item>
            </a-col>
            <a-col :span="12">
              <a-form-item label="表单名称" v-bind="validateInfos.title" id="OnlinePagesForm-title" name="title">
                <a-input v-model:value="formData.title" placeholder="请输入表单名称" allow-clear />
              </a-form-item>
            </a-col>
          </a-row>
          <a-row>
            <a-col :span="12">
              <a-form-item label="访问地址" v-bind="validateInfos.viewPath" id="OnlinePagesForm-viewPath" name="viewPath">
                <a-input v-model:value="formData.viewPath" placeholder="请输入访问地址" allow-clear />
              </a-form-item>
            </a-col>
            <a-col :span="12">
              <a-form-item label="表单编码" v-bind="validateInfos.pageKey" id="OnlinePagesForm-pageKey" name="pageKey">
                <a-input v-model:value="formData.pageKey" placeholder="请输入表单编码" allow-clear />
              </a-form-item>
            </a-col>
          </a-row>
        </a-form>
      </template>
    </JFormContainer>

    <!-- 子表单区域 -->
    <a-tabs v-model:activeKey="activeKey" animated style="overflow: hidden">
      <a-tab-pane tab="表单注册元素列表" key="onlinePageElements" :forceRender="true">
        <j-vxe-table
          :keep-source="true"
          resizable
          keyboardEdit
          rowNumber
          ref="onlinePageElementsTableRef"
          :loading="onlinePageElementsTable.loading"
          :columns="onlinePageElementsTable.columns"
          :dataSource="onlinePageElementsTable.dataSource"
          :height="340"
          :disabled="disabled"
          :toolbarConfig="toolbarConfig"
          rowSelection
          toolbar
          :tree-config="onlinePageElementsTable.treeConfig"
        >
          <template #toolbarPrefix v-if="formData.cgformHeadId">
            <a-button type="primary" preIcon="ant-design:reload-outlined" @click="reloadData">同步表单元素</a-button>
          </template>
        </j-vxe-table>
      </a-tab-pane>
    </a-tabs>
  </a-spin>
</template>

<script lang="ts">
  import { defineComponent, ref, reactive, computed, toRaw, nextTick, watch } from 'vue';
  import { useValidateAntFormAndTable } from '/@/hooks/system/useJvxeMethods';
  import { queryDataById, elementList, list, saveOrUpdate, elementDefaultList, formList, formInfo } from '../CgformApprovePage.api';
  import { JVxeTable } from '/@/components/base/JVxeTable';
  import { VxeTableEvents } from 'vxe-table';
  import { onlCgformApprovePageElementColumns } from '../CgformApprovePage.data';
  import JFormContainer from '/@/components/Form/src/container/JFormContainer.vue';
  import { ApiSelect } from '/@/components/Form/index';
  import { Form } from 'ant-design-vue';
  import { unref } from 'vue';
  import { message } from 'ant-design-vue';

  const useForm = Form.useForm;

  export default defineComponent({
    name: 'CgformApprovePageForm',
    components: {
      JVxeTable,
      JFormContainer,
      ApiSelect,
    },
    props: {
      formDisabled: {
        type: Boolean,
        default: false,
      },
      formBpm: { type: Boolean, default: true },
    },
    emits: ['success'],
    setup(props, { emit }) {
      const loading = ref(false);
      const formRef = ref();
      const onlinePageElementsTableRef = ref();
      const pages = ref<unknown[]>([]);
      const onlinePageElementsTable = ref<Record<string, any>>({
        loading: false,
        columns: onlCgformApprovePageElementColumns,
        dataSource: [],
        treeConfig: {
          transform: true,
          rowField: 'id',
          parentField: 'parentId',
        },
      });
      // 工具栏的按钮配置
      const toolbarConfig = reactive({
        // add 新增按钮；save 保存按钮；remove 删除按钮
        btn: ['add', 'remove'],
        //prefix 按钮前方位置显示的内容 suffix 按钮后方位置显示的内容
        slot: ['prefix'],
      });
      const activeKey = ref('onlinePageElements');
      const formData = reactive<Record<string, any>>({
        id: '',
        cgformHeadId: '',
        pageKey: '',
        viewPath: '',
        title: '',
      });
      const searchParams = reactive({
        tableName: '',
      });

      function onSearch(value: string) {
        searchParams.tableName = `*${value}*`;
      }

      //表单验证
      const validatorRules = reactive({
        cgformHeadId: [{ required: true, message: '请输入表单!' }],
        pageKey: [
          { required: true, message: '请输入表单编码!' },
          { pattern: /^[^0-9][A-z0-9]*$/, message: '只能用英文字母大小写及数字，但不能以数字开头!' },
          { asyncValidator: validatePageKey },
        ],
        viewPath: [{ required: true, message: '请输入前端路由地址!' }],
        title: [{ required: true, message: '请输入页面名称!' }],
      });
      const { resetFields, validate, validateInfos } = useForm(formData, validatorRules, { immediate: false });
      const dbData = {};
      const formItemLayout = {
        labelCol: { xs: { span: 24 }, sm: { span: 5 } },
        wrapperCol: { xs: { span: 24 }, sm: { span: 16 } },
      };

      // 表单禁用
      const disabled = computed(() => {
        return props.formBpm || props.formDisabled;
      });

      async function validatePageKey(_rule, pageKey) {
        const res = await list({ pageKey, pageNo: 1, pageSize: 1 });
        if (res.total) {
          if (res.records[0].id === formData.id) {
            return Promise.resolve();
          }
          return Promise.reject('表单编码已存在！');
        } else {
          return Promise.resolve();
        }
      }

      async function selectForm(_, option, type?: 'reset') {
        formData.title = option.tableTxt;
        // onlinePageElementsTable.columns[3].options = [];
        // onlinePageElementsTable.dataSource = [];

        await loadDefaultElements(_, option.label, '', type);
        if (!option.subTableStr) {
          return;
        }
        const res = await formInfo({ code: _ });
        // 上级元素
        res.sub.forEach(async ({ id, tableName }) => {
          await loadDefaultElements(id, tableName, option.label, type);
        });
      }

      const reloadData = async () => {
        const options = unref(pages).find((item) => item.id === formData.cgformHeadId);
        options.label = options.tableName;
        await selectForm(formData.cgformHeadId, options, 'reset');
        message.success('同步成功');
      };

      async function loadDefaultElements(headId: string, tableName: string, parent?: string, type?: 'reset') {
        const res = await elementDefaultList({ headId });
        let oldDataSource = unref(onlinePageElementsTableRef).getTableData() || [];
        // 查找关联了主表的字段
        const index = res.findIndex(({ mainTable }) => mainTable && mainTable === parent);
        // 上级元素前置
        if (index !== -1) {
          res.unshift(...res.splice(index, 1));
        }
        // 上级元素下拉框设置数据
        const parentElementId = index !== -1 ? tableName + '_' + res[0].dbFieldName : null;
        if (parentElementId) {
          onlinePageElementsTable.value.columns[3].options.push({
            label: res[0].dbFieldTxt,
            value: parentElementId,
          });
        }
        // 表单字段转为元素
        const elements = res.map(({ dbFieldName, dbFieldTxt, id }, index) => ({
          isEnable: 1,
          elementId: tableName + '_' + dbFieldName,
          id,
          name: dbFieldTxt,
          // 子表第一项是其他元素的上级元素
          parentElementId: index ? parentElementId : null,
          type: 'element',
        }));
        // 延迟更新子表数据
        const allIds = elements.map((item) => item.id);
        if (type === 'reset') {
          oldDataSource = oldDataSource.filter((item, index) => {
            if (!allIds.includes(item.id)) {
              item.id = item.id || +new Date() + index;
              return item;
            }
          });
        } else {
          oldDataSource = [];
        }
        onlinePageElementsTable.value.dataSource = [...elements, ...oldDataSource];
      }
      async function loadForms() {
        const res = await formList({ pageNo: 1, pageSize: 999 });
        pages.value = res.records;
      }

      function add() {
        resetFields();
        searchParams.tableName = '';
        onlinePageElementsTable.value.dataSource = [];
      }

      async function edit(row) {
        // 主表数据
        await queryMainData(row.id);
        // 子表数据
        const subData = await elementList(row.id);
        // 上级元素
        const parentId = [...new Set(subData.records.map((item) => (item.parentElementId ? item.parentElementId : 'NoParentXXXX')))];
        onlinePageElementsTable.value.columns[3].options = subData.records
          .filter((item) => parentId.includes(item.elementId))
          .map(({ name, elementId }) => ({ label: name, value: elementId }));
        console.log(subData.records, 'subData.records');
        // 延迟更新子表数据
        nextTick(() => {
          onlinePageElementsTable.value.dataSource = subData.records;
        });
      }

      async function queryMainData(id) {
        const row = await queryDataById(id);
        resetFields();
        const tmpData = {};
        Object.keys(formData).forEach((key) => {
          if (row.hasOwnProperty(key)) {
            tmpData[key] = row[key];
          }
        });
        //赋值
        Object.assign(formData, tmpData);

        const res = await formInfo({ code: formData.cgformHeadId });
        if (res?.main) {
          onSearch(res.main.tableName);
        }
      }

      const { getSubFormAndTableData, transformData } = useValidateAntFormAndTable(activeKey, {
        onlextCgformApprovePageElement: onlinePageElementsTableRef,
      });

      interface ErrorField {
        name: string;
      }
      interface InvalidResult {
        errorFields: ErrorField[];
      }
      async function getFormData() {
        try {
          // 触发表单验证
          await validate<InvalidResult>();
        } catch (err) {
          const { errorFields } = err as InvalidResult;
          if (errorFields) {
            const firstField = errorFields[0];
            if (firstField) {
              formRef.value.scrollToField(firstField.name, { behavior: 'smooth', block: 'center' });
            }
          }
          return Promise.reject(errorFields);
        }
        return transformData(toRaw(formData));
      }

      async function submitForm() {
        const mainData = await getFormData();
        const subData = await getSubFormAndTableData();
        const values = Object.assign({}, dbData, mainData, subData);
        const isUpdate = values.id ? true : false;
        await saveOrUpdate(values, isUpdate);
        //关闭弹窗
        emit('success');
      }

      function setFieldsValue(values) {
        if (values) {
          Object.keys(values).map((k) => {
            formData[k] = values[k];
          });
        }
      }

      /**
       * 值改变事件触发-树控件回调
       * @param key
       * @param value
       */
      function handleFormChange(key, value) {
        formData[key] = value;
      }

      loadForms();

      return {
        onlinePageElementsTableRef,
        onlinePageElementsTable,
        validatorRules,
        validateInfos,
        reloadData,
        toolbarConfig,
        activeKey,
        loading,
        pages,
        formData,
        formList,
        selectForm,
        setFieldsValue,
        handleFormChange,
        formItemLayout,
        disabled,
        getFormData,
        submitForm,
        add,
        edit,
        formRef,
        searchParams,
        onSearch,
      };
    },
  });
</script>
<style lang="less" scoped>
  .ant-tabs-tabpane.sub-one-form {
    max-height: 340px;
    overflow: auto;
  }
  .header-title {
    padding: 8px 0px;
  }

  .form-content-title {
    padding: 10px 10px 10px 0;
    background-color: #f7f8fa;
    font-size: 16px;
    margin-bottom: 16px;
  }
  .form-content-title::before {
    display: inline-block;
    content: '|';
    width: 5px;
    background: #009a7a;
    color: #009a7a;
    margin-right: 10px;
  }
</style>
